package com.tronsis.distribution.pay.wechatpay;

import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.util.Xml;
import android.widget.Toast;

import com.tencent.mm.opensdk.constants.Build;
import com.tencent.mm.opensdk.modelpay.PayReq;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
import com.tronsis.distribution.Constants;
import com.tronsis.distribution.R;
import com.tronsis.library.util.StringUtil;
import com.tronsis.library.widget.LoadingProgressDialog;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.xmlpull.v1.XmlPullParser;

import java.io.StringReader;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;

public class WechatPay {

    /**
     * 微信支付
     **/
//    private static final String APP_ID = "wx40273cf9119a498a";   // 微信开放平台appid
//    private static final String MACH_ID = "1375489102";    //  微信商户号
//    private static final String APP_KEY = "nPILtU2IJo1L4R3QvUGwUIqskrjWLCit";    // 微信API密钥，在商户平台设置
    private static final String TAG = "WechatPay";
    private PayReq req;
    private IWXAPI msgApi;
    private Map<String, String> resultunifiedorder;
    private Context mContext;

    public WechatPay(Context context) {
        msgApi = WXAPIFactory.createWXAPI(context, null);
        req = new PayReq();
        this.mContext = context;
    }


    /**
     * 统一下单支付
     * @param data
     */
  public void pay(WeChatPayOrderBean data){
        msgApi.registerApp(Constants.WX_APP_ID);
        req.appId = data.getAppid();
        req.partnerId = data.getPartnerid();
        req.prepayId = data.getPrepayid();
        req.packageValue = data.getPackageX();
        req.nonceStr = data.getNoncestr();
        req.timeStamp = data.getTimestamp();
        req.sign = data.getSign();
        msgApi.sendReq(req);
    }


    /**
     * 微信支付
     *
     * @param title     订单标题
     * @param detail    订单详情
     * @param orderNo   订单号
     * @param totalFee  总金额（单位为分，即1表示1分）
     * @param attach    额外附带的数据，用于服务器异步通知使用
     * @param notifyUrl
     */
    public void pay(String title, String detail, String orderNo, String totalFee, String attach, String notifyUrl) {
        boolean isPaySupported = msgApi.getWXAppSupportAPI() >= Build.PAY_SUPPORTED_SDK_INT;
        if (!isPaySupported) {
            Toast.makeText(mContext, "Your Wechat maybe too old to use wechat pay!", Toast.LENGTH_SHORT).show();
            return;
        }
        GetPrepayIdTask getPrepayId = new GetPrepayIdTask(title, detail, orderNo, totalFee, attach, notifyUrl);
        getPrepayId.execute();
    }

    /**
     * 生成签名
     */
    private String genPackageSign(List<NameValuePair> params) {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < params.size(); i++) {
            sb.append(params.get(i).getName());
            sb.append('=');
            sb.append(params.get(i).getValue());
            sb.append('&');
        }
        sb.append("key=");
        sb.append(Constants.WX_APP_ID);

        String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
        Log.e("orion", packageSign);
        return packageSign;
    }

    private String genAppSign(List<NameValuePair> params) {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < params.size(); i++) {
            sb.append(params.get(i).getName());
            sb.append('=');
            sb.append(params.get(i).getValue());
            sb.append('&');
        }
        sb.append("key=");
        sb.append(Constants.WX_APP_ID);

        String appSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
        Log.e("orion", appSign);
        return appSign;
    }

    private String toXml(List<NameValuePair> params) {
        StringBuilder sb = new StringBuilder();
        sb.append("<xml>");
        for (int i = 0; i < params.size(); i++) {
            sb.append("<" + params.get(i).getName() + ">");

            sb.append(params.get(i).getValue());
            sb.append("</" + params.get(i).getName() + ">");
        }
        sb.append("</xml>");

        Log.e("orion", sb.toString());
        return sb.toString();
    }

    private class GetPrepayIdTask extends AsyncTask<Void, Void, Map<String, String>> {

        private String body;
        private String detail;
        private String orderNo;
        private String totalFee;
        private String attach;
        private String notifyUrl;
        private LoadingProgressDialog dialog;

        public GetPrepayIdTask(String body, String detail, String orderNo, String totalFee, String attach, String notifyUrl) {
            super();
            this.body = body;
            this.detail = detail;
            this.orderNo = orderNo;
            this.totalFee = totalFee;
            this.attach = attach;
            this.notifyUrl = notifyUrl;
        }

        @Override
        protected void onPreExecute() {
            dialog = new LoadingProgressDialog(mContext, R.style.CustomProgressDialog);
            dialog.show("正在打开微信支付..");
        }

        @Override
        protected void onPostExecute(Map<String, String> result) {
            resultunifiedorder = result;
            sendPayReq();

            if (dialog != null) {
                dialog.dismiss();
            }
        }

        @Override
        protected void onCancelled() {
            super.onCancelled();
        }

        @Override
        protected Map<String, String> doInBackground(Void... params) {

            String url = String.format("https://api.mch.weixin.qq.com/pay/unifiedorder");
            String entity = genProductArgs(body, detail, orderNo, totalFee, attach, notifyUrl);

            byte[] buf = Util.httpPost(url, entity);

            String content = new String(buf);
            Log.e("orion", content);
            Map<String, String> xml = decodeXml(content);

            return xml;
        }
    }

    public Map<String, String> decodeXml(String content) {

        try {
            Map<String, String> xml = new HashMap<String, String>();
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(new StringReader(content));
            int event = parser.getEventType();
            while (event != XmlPullParser.END_DOCUMENT) {

                String nodeName = parser.getName();
                switch (event) {
                    case XmlPullParser.START_DOCUMENT:

                        break;
                    case XmlPullParser.START_TAG:

                        if ("xml".equals(nodeName) == false) {
                            // 实例化student对象
                            xml.put(nodeName, parser.nextText());
                        }
                        break;
                    case XmlPullParser.END_TAG:
                        break;
                }
                event = parser.next();
            }

            return xml;
        } catch (Exception e) {
            Log.e("orion", e.toString());
        }
        return null;

    }

    private String genNonceStr() {
        Random random = new Random();
        return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
    }

    private long genTimeStamp() {
        return System.currentTimeMillis() / 1000;
    }

    private String genOutTradNo() {
        Random random = new Random();
        return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
    }

    //
    private String genProductArgs(String body, String detail, String orderNo, String totalFee, String attach, String notifyUrl) {
        StringBuffer xml = new StringBuffer();

        try {
            String nonceStr = genNonceStr();

            xml.append("</xml>");
            List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
            packageParams.add(new BasicNameValuePair("appid", Constants.WX_APP_ID));
            if (!StringUtil.isBlank(attach)) {
                packageParams.add(new BasicNameValuePair("attach", attach));
            }
            packageParams.add(new BasicNameValuePair("body", body));
            packageParams.add(new BasicNameValuePair("detail", detail));
            packageParams.add(new BasicNameValuePair("mch_id", Constants.WX_PAY_MACH_ID));
            packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));
            packageParams.add(new BasicNameValuePair("notify_url", notifyUrl)); // 异步回调支付结果URL
            packageParams.add(new BasicNameValuePair("out_trade_no", orderNo));
            packageParams.add(new BasicNameValuePair("spbill_create_ip", "127.0.0.1"));
            packageParams.add(new BasicNameValuePair("total_fee", totalFee));
            packageParams.add(new BasicNameValuePair("trade_type", "APP"));

            String sign = genPackageSign(packageParams);
            packageParams.add(new BasicNameValuePair("sign", sign));

            String xmlstring = toXml(packageParams);
            xmlstring = new String(xmlstring.getBytes(), "iso-8859-1");
            Log.e(TAG, "genProductArgs:"+xmlstring);
            return xmlstring;

        } catch (Exception e) {
            return null;
        }

    }

    private void genPayReq() {

        req.appId = Constants.WX_APP_ID;
        req.partnerId = Constants.WX_PAY_MACH_ID;
        req.prepayId = resultunifiedorder.get("prepay_id");
        req.packageValue = "Sign=WXPay";
        req.nonceStr = genNonceStr();
        req.timeStamp = String.valueOf(genTimeStamp());

        List<NameValuePair> signParams = new LinkedList<NameValuePair>();
        signParams.add(new BasicNameValuePair("appid", req.appId));
        signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));
        signParams.add(new BasicNameValuePair("package", req.packageValue));
        signParams.add(new BasicNameValuePair("partnerid", req.partnerId));
        signParams.add(new BasicNameValuePair("prepayid", req.prepayId));
        signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));

        req.sign = genAppSign(signParams);

        Log.e("orion", signParams.toString());

    }

    private void sendPayReq() {
        genPayReq();
        msgApi.registerApp(Constants.WX_APP_ID);
        msgApi.sendReq(req);
    }
}
